﻿using System;
using System.Collections.Generic;
using System.Text;

namespace JoyServer.Events
{
	/// <summary>
	/// イベント処理用クラス
	/// </summary>
	class EventDispatcher
	{
		/// <summary>
		/// イベントとイベントリスナの一覧
		/// </summary>
		private Dictionary<string, EventFunction> events;

		/// <summary>
		/// コンストラクタ
		/// </summary>
		public EventDispatcher()
		{
			events = new Dictionary<String, EventFunction>();
		}

		/// <summary>
		/// イベント処理メソッドを追加する
		/// </summary>
		/// <param name="type">イベントのタイプ</param>
		/// <param name="listener">そのタイプのイベントを処理するメソッド</param>
		public void addEventListener(String type, EventFunction listener)
		{
			// 引数チェック
			if (type == null || type == "")
				return;
			if (listener == null)
				return;

			if (isTypeExist(type))
				addListener(type, listener);
			else
				addNewListener(type, listener);
		}

		/// <summary>
		/// イベント処理メソッドを取り除く
		/// </summary>
		/// <param name="type"></param>
		/// <param name="listener"></param>
		public void removeEventListener(String type, EventFunction listener)
		{
			// 引数チェック
			if (type == null || type == "")
				return;
			if (listener == null)
				return;

			if (isTypeExist(type))
				removeListener(type, listener);
		}

		/// <summary>
		/// イベント処理メソッドが存在するか確認する
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public bool hasEventListener(String type)
		{
			// 引数チェック
			if (type == null || type == "")
				return false;

			if (isTypeExist(type))
			{
				return true;
			}
			return false;
		}

		/// <summary>
		/// イベントを発行する
		/// </summary>
		/// <param name="e">伝播させたいイベントクラス</param>
		/// <returns></returns>
		public bool dispatchEvent(Event e)
		{
			// 引数チェック
			if (e == null)
				return false;

			String type = e.type;

			if (isTypeExist(type))
				callEventFunctions(type, e);
			return true;
		}


		/// <summary>
		/// イベントタイプが既に存在するか確認する
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		private bool isTypeExist(String type)
		{
			return events.ContainsKey(type);
		}

		/// <summary>
		/// 既に存在するイベント処理関数一覧にイベントを追加する
		/// </summary>
		/// <param name="type"></param>
		/// <param name="listener"></param>
		private void addListener(String type, EventFunction listener)
		{
			events[type] += new EventFunction(listener);
		}

		/// <summary>
		/// 新しくイベント処理関数を作成して追加する
		/// </summary>
		/// <param name="type"></param>
		/// <param name="listener"></param>
		private void addNewListener(String type, EventFunction listener)
		{
			EventFunction eventFunction;
			eventFunction = new EventFunction(listener);
			events.Add(type, eventFunction);
		}

		/// <summary>
		/// イベント処理関数を取り除く
		/// </summary>
		/// <param name="type"></param>
		/// <param name="listener"></param>
		private void removeListener(String type, EventFunction listener)
		{
			events[type] -= listener;
		}

		/// <summary>
		/// イベント処理関数を呼び出す
		/// </summary>
		/// <param name="type"></param>
		/// <param name="e"></param>
		private void callEventFunctions(String type, Event e)
		{
			events[type](e);
		}
	}
}
